﻿using System;
using System.Collections.Generic;

namespace Microsoft.Popfly.GameCreator.GameEngine.Events
{
    public class CollisionEventArgsFilter //: EventArgsFilter
    {
        private bool[] m_directions;
        private CollisionClass[] m_collisionClasses;

        public CollisionEventArgsFilter(CollisionClass[] collisionClasses, Data.CollisionEventInfo collisionEventInfo)
        {
            if (collisionClasses.Length != 2)
            {
                throw new ArgumentException(
                    Utils.ErrorMessagePrefix +
                    "CollisionEventArgsFilter expectes collisionClasses to have a length of 2.  " +
                    "collisionClasses was passed in with a length of '" + collisionClasses.Length +
                    "'."
                    );
            }

            m_collisionClasses = collisionClasses;
            if (collisionEventInfo.directions != null)
            {
                m_directions = new bool[5];
                foreach (KeyValuePair<String, Data.CollisionDirectionInfo> kvp in collisionEventInfo.directions)
                {
                    int index = -1;
                    switch (kvp.Value.Name)
                    {
                        case "top":
                            index = (int)CollisionDirectionArg.FilterDirections.FILTER_TOP;
                            break;
                        case "bottom":
                            index = (int)CollisionDirectionArg.FilterDirections.FILTER_BOTTOM;
                            break;
                        case "left":
                            index = (int)CollisionDirectionArg.FilterDirections.FILTER_LEFT;
                            break;
                        case "right":
                            index = (int)CollisionDirectionArg.FilterDirections.FILTER_RIGHT;
                            break;
                    }
                    m_directions[index] = kvp.Value.valid;
                }
            }
            else
            {
                m_directions = null;
            }


            // If all directions are set to true, just null it out
            // since we won't need to check
            if (m_directions != null &&
                m_directions[(int)CollisionDirectionArg.FilterDirections.FILTER_TOP] &&
                m_directions[(int)CollisionDirectionArg.FilterDirections.FILTER_BOTTOM] &&
                m_directions[(int)CollisionDirectionArg.FilterDirections.FILTER_LEFT] &&
                m_directions[(int)CollisionDirectionArg.FilterDirections.FILTER_RIGHT])
            {
                m_directions = null;
            }
        }

        private static bool MatchesClass(Actor actor, CollisionClass collisionClass)
        {
            switch (collisionClass.Type)
            {
                case CollisionClass.SubType.ACTOR :
                    return (collisionClass.ActorOrInstance == actor.ActorName);
                case CollisionClass.SubType.ACTORINSTANCE :
                    return (collisionClass.ActorOrInstance == actor.Name);
                case CollisionClass.SubType.NONSOLID :
                    return !actor.CurrentState.IsSolid;
                case CollisionClass.SubType.SOLID :
                    return actor.CurrentState.IsSolid;
                case CollisionClass.SubType.ALL:
                    return true;
                default :
                    throw new NotImplementedException(
                        Utils.ErrorMessagePrefix +
                        "CheckArgs doesn't know how to handle collision classes of type '" +
                        collisionClass.Type.ToString() +
                        "'."
                        );
            }
        }

        public bool CheckArgs(CollisionEventArgs args)
        {
            if (m_directions == null)
            {
                return true;
            }
            else
            {
                bool actor1MatchesClass1 = MatchesClass(args.Actor1, m_collisionClasses[0]);
                bool actor1MatchesClass2 = MatchesClass(args.Actor1, m_collisionClasses[1]);
                bool actor2MatchesClass1 = MatchesClass(args.Actor2, m_collisionClasses[0]);
                bool actor2MatchesClass2 = MatchesClass(args.Actor2, m_collisionClasses[1]);

                if (actor1MatchesClass1 && actor2MatchesClass2)
                {
                    if (m_directions[(int)args.Actor1Direction.FilterDirection])
                        return true;
                }

                if (actor1MatchesClass2 && actor2MatchesClass1)
                {
                    if (m_directions[(int)args.Actor2Direction.FilterDirection])
                        return true;
                }
                return false;
            }

        }
    }
}
